#ifndef REMOTESERVER_H
#define REMOTESERVER_H

#include <QWidget>

#include <QTcpServer>
#include <QTcpSocket>
#include <QUdpSocket>
#include <QImage>
#include <QScreen>
#include <QApplication>
#include <QBuffer>

//#ifdef Q_OS_LINUX
//#include <X11/Xlib.h>
//#include <linux/input.h>
//#include <linux/uinput.h>
//#endif

#include <fcntl.h>
#include <unistd.h>

#define CONTROL_PORT 8888
#define VIDEO_PORT 8889
#define KEY_AUTH 0x01
#define KEY_MOUSE_MOVE 0x11
#define KEY_MOUSE_CLICK 0x12
#define KEY_MOUSE_WHEEL 0x13
#define KEY_KEYBOARD 0x10
#define KEY_FRAME_REQUEST 0x30


#include <QTimer>

class RemoteServer : public QObject {
    Q_OBJECT
public:
    RemoteServer(QObject *parent = nullptr) : QObject(parent) {
        tcpServer = new QTcpServer(this);
        udpSocket = new QUdpSocket(this);
        timer = new QTimer(this);
        uinput_fd = -1;

        if (!tcpServer->listen(QHostAddress::Any, CONTROL_PORT)) {
            qCritical() << "Cannot start server:" << tcpServer->errorString();
            return;
        }

        connect(tcpServer, &QTcpServer::newConnection, this, &RemoteServer::newConnection);
        connect(timer, &QTimer::timeout, this, &RemoteServer::sendFrame);
        qInfo() << "Server started on port" << CONTROL_PORT;

        if (!udpSocket->bind(VIDEO_PORT)) {
            qCritical() << "Cannot bind UDP socket:" << udpSocket->errorString();
        }

        createUinputDevice();
    }

    ~RemoteServer() {
//#ifdef Q_OS_LINUX
//        if (uinput_fd >= 0) {
//            ioctl(uinput_fd, UI_DEV_DESTROY);
//            close(uinput_fd);
//        }
//#endif
    }

private slots:
    void newConnection() {
        QTcpSocket *client = tcpServer->nextPendingConnection();
        if (controlSocket) {
            qWarning() << "Only one client allowed";
            client->close();
            delete client;
            return;
        }

        controlSocket = client;
        connect(controlSocket, &QTcpSocket::readyRead, this, &RemoteServer::readClientData);
        connect(controlSocket, &QTcpSocket::disconnected, this, [=]() {
            controlSocket->deleteLater();
            controlSocket = nullptr;
            timer->stop();
            qInfo() << "Client disconnected";
        });

        qInfo() << "New client connected:" << client->peerAddress();
        timer->start(1000 / 3); // 30 FPS
    }

    void readClientData() {
        while (controlSocket->bytesAvailable() >= 5) {
            char command;
            controlSocket->read(&command, 1);

            switch (command) {
            case KEY_AUTH: {
                QByteArray authData = controlSocket->read(4);
                if (authData != QByteArray("PASS")) {
                    controlSocket->disconnectFromHost();
                    qWarning() << "Authentication failed";
                }
                break;
            }
            case KEY_MOUSE_MOVE: {
                qint16 x, y;
                controlSocket->read((char*)&x, 2);
                controlSocket->read((char*)&y, 2);
                injectMouseEvent(x, y, lastButtons);
                break;
            }
            case KEY_MOUSE_CLICK: {
                quint8 buttons;
                controlSocket->read((char*)&buttons, 1);
                lastButtons = buttons;
                injectMouseEvent(lastX, lastY, buttons);
                break;
            }
            case KEY_KEYBOARD: {
                quint8 keyState;
                quint32 keyCode;
                controlSocket->read((char*)&keyState, 1);
                controlSocket->read((char*)&keyCode, 4);
                injectKeyEvent(keyCode, keyState);
                break;
            }
            case KEY_FRAME_REQUEST:
                // 立即发送一帧
                sendFrame();
                break;
            }
        }
    }

    void sendFrame() {
        if (!controlSocket) return;

        QScreen *screen = QGuiApplication::primaryScreen();
        if (!screen) return;
        QPixmap screenshot = screen->grabWindow(0,0);

        QImage image = screenshot.toImage();qDebug()<<"s-1";
        if (image.isNull()) return;qDebug()<<"s-2";

        // 压缩为JPEG (质量70%)
        QByteArray jpegData;
        QBuffer buffer(&jpegData);
        buffer.open(QIODevice::WriteOnly);
        image.save(&buffer, "JPEG", 70);image.save(QApplication::applicationDirPath()+"/desk.jpg");

        // 分片发送 (Max UDP size: 65535)
        const int MAX_SIZE = 60000;
        int fragments = (jpegData.size() + MAX_SIZE - 1) / MAX_SIZE;

        for (int i = 0; i < fragments; i++) {
            int offset = i * MAX_SIZE;
            int size = qMin(MAX_SIZE, jpegData.size() - offset);
            QByteArray packet;
            QDataStream stream(&packet, QIODevice::WriteOnly);

            stream << (quint16)0xFF01 // 帧头
                   << (quint32)frameCounter // 帧ID
                   << (quint16)fragments // 总片段数
                   << (quint16)i // 当前片段索引
                   << QByteArray(jpegData.constData() + offset, size);

            udpSocket->writeDatagram(packet, controlSocket->peerAddress(), VIDEO_PORT);
        }

        frameCounter++;qDebug()<<"s-3";
    }

private:
    void createUinputDevice() {
//        uinput_fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
//        if (uinput_fd < 0) {
//            qCritical() << "Cannot open uinput device";
//            return;
//        }

//        // 设置输入设备
//        ioctl(uinput_fd, UI_SET_EVBIT, EV_KEY);
//        ioctl(uinput_fd, UI_SET_EVBIT, EV_REL);
//        ioctl(uinput_fd, UI_SET_EVBIT, EV_SYN);

//        // 设置支持的键
//        for (int key = KEY_ESC; key <= KEY_COMPOSE; key++) {
//            ioctl(uinput_fd, UI_SET_KEYBIT, key);
//        }
//        ioctl(uinput_fd, UI_SET_KEYBIT, BTN_MOUSE);
//        ioctl(uinput_fd, UI_SET_KEYBIT, BTN_LEFT);
//        ioctl(uinput_fd, UI_SET_KEYBIT, BTN_RIGHT);
//        ioctl(uinput_fd, UI_SET_KEYBIT, BTN_MIDDLE);

//        // 设置相对坐标
//        ioctl(uinput_fd, UI_SET_RELBIT, REL_X);
//        ioctl(uinput_fd, UI_SET_RELBIT, REL_Y);
//        ioctl(uinput_fd, UI_SET_RELBIT, REL_WHEEL);

//        uinput_user_dev uidev;
//        memset(&uidev, 0, sizeof(uidev));
//        strncpy(uidev.name, "Qt Remote Mouse", UINPUT_MAX_NAME_SIZE);
//        uidev.id.bustype = BUS_VIRTUAL;
//        uidev.id.vendor  = 0x1;
//        uidev.id.product = 0x1;
//        uidev.id.version = 1;

//        write(uinput_fd, &uidev, sizeof(uidev));
//        ioctl(uinput_fd, UI_DEV_CREATE);

//        qInfo() << "Virtual input device created";
    }

    void injectMouseEvent(qint16 x, qint16 y, quint8 buttons) {
//        if (uinput_fd < 0) return;

//        struct input_event ev[4];
//        memset(ev, 0, sizeof(ev));
//        gettimeofday(&ev[0].time, NULL);
//        gettimeofday(&ev[1].time, NULL);
//        gettimeofday(&ev[2].time, NULL);
//        gettimeofday(&ev[3].time, NULL);

//        // 相对移动
//        ev[0].type = EV_REL;
//        ev[0].code = REL_X;
//        ev[0].value = x - lastX;

//        ev[1].type = EV_REL;
//        ev[1].code = REL_Y;
//        ev[1].value = y - lastY;

//        // 按钮状态
//        ev[2].type = EV_KEY;
//        ev[2].code = BTN_LEFT;
//        ev[2].value = (buttons & 0x01) ? 1 : 0;

//        ev[3].type = EV_KEY;
//        ev[3].code = BTN_RIGHT;
//        ev[3].value = (buttons & 0x02) ? 1 : 0;

//        // 同步事件
//        struct input_event syn;
//        memset(&syn, 0, sizeof(syn));
//        syn.type = EV_SYN;
//        syn.code = SYN_REPORT;

//        write(uinput_fd, ev, sizeof(ev));
//        write(uinput_fd, &syn, sizeof(syn));

//        lastX = x;
//        lastY = y;
    }

    void injectKeyEvent(quint32 key, quint8 state) {
//        if (uinput_fd < 0) return;

//        struct input_event ev;
//        memset(&ev, 0, sizeof(ev));
//        gettimeofday(&ev.time, NULL);

//        ev.type = EV_KEY;
//        ev.code = key;
//        ev.value = state; // 0 = release, 1 = press

//        struct input_event syn;
//        memset(&syn, 0, sizeof(syn));
//        syn.type = EV_SYN;
//        syn.code = SYN_REPORT;

//        write(uinput_fd, &ev, sizeof(ev));
//        write(uinput_fd, &syn, sizeof(syn));
    }

private:
    QTcpServer *tcpServer;
    QUdpSocket *udpSocket;
    QTcpSocket *controlSocket = nullptr;
    QTimer *timer;

    // uinput
    int uinput_fd;
    qint16 lastX = 0;
    qint16 lastY = 0;
    quint8 lastButtons = 0;
    quint32 frameCounter = 0;
};


#endif // REMOTESERVER_H
